/* DomainErzeuger.java
 *
 * Author:	Malcolm Staudacher
 * Date:	May 1, 2008
 *
 */

package ocumed.applikation.domainhandling;

import java.util.HashMap;
import java.util.Vector;

import ocumed.domaene.behandlung.DBehandlung;
import ocumed.domaene.behandlung.DLeistungscode;
import ocumed.domaene.behandlung.DMedikament;
import ocumed.domaene.behandlung.DMedikamentVerordnung;
import ocumed.domaene.behandlung.DPosition;
import ocumed.domaene.benutzerverwaltung.DBenutzer;
import ocumed.domaene.benutzerverwaltung.DBenutzerGruppe;
import ocumed.domaene.benutzerverwaltung.arztverwaltung.DArzt;
import ocumed.domaene.benutzerverwaltung.arztverwaltung.DFehlzeit;
import ocumed.domaene.benutzerverwaltung.arztverwaltung.DOrdinationsZeit;
import ocumed.domaene.dokument.DRezept;
import ocumed.domaene.patientenverwaltung.DLand;
import ocumed.domaene.patientenverwaltung.DOrt;
import ocumed.domaene.patientenverwaltung.DPatient;
import ocumed.domaene.terminverwaltung.DTermin;
import ocumed.domaene.terminverwaltung.DTerminArt;
import ocumed.domaene.terminverwaltung.DTerminkalender;
import ocumed.teams.IBenutzer;
import ocumed.teams.IPatient;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * internal domain brain
 * 
 * @author Malcolm Staudacher
 * @author Daniel Rudigier
 *
 */
public class DomainHandler {
    private static final int pollinterval = 5000; // msec
    private static final Log log = LogFactory.getLog(DomainHandler.class);
    private static DomainHandler instance;
    
    // current user
	static IBenutzer actIBenutzer;
    
    // domain object creators
    public static BenutzerErzeugung be = new BenutzerErzeugung();
    public static PatientenErzeugung pe = new PatientenErzeugung();
    public static TerminErzeugung te = new TerminErzeugung();
    public static OrtErzeugung oe = new OrtErzeugung();
    public static MedikamentErzeugung me = new MedikamentErzeugung();
    public static WarteschlangeErzeugung we = new WarteschlangeErzeugung();

	// required domain objects
	private Vector<DTermin> m_termine;
	private Vector<DBenutzer> m_benutzer;
	private Vector<DFehlzeit> m_fehlzeiten;
	private Vector<DOrdinationsZeit> m_ordZeiten;
	private Vector<DTerminkalender> m_kalender;
	private Vector<DBenutzerGruppe> m_gruppen;
	private Vector<DTerminArt> m_arten;
	private Vector<DPatient> m_patienten;
	private Vector<DArzt> m_aerzte;
	private Vector<DLand> m_laender;
	private Vector<DOrt> m_orte;
	private Vector<DTerminArt> m_terminArten;
	private HashMap<Integer, DMedikament> m_medikamente;
	private Vector<DBehandlung> m_behandlungen;
	private Vector<DRezept> m_rezepte;
	private Vector<DMedikamentVerordnung> m_verordnungen;
	private Vector<DPosition> m_positionen;
	private Vector<DLeistungscode> m_leistungscodes;

    /**
     * 
     * constructor
     *
     */
	private DomainHandler() {
        m_benutzer = new Vector<DBenutzer>();
        m_ordZeiten = new Vector<DOrdinationsZeit>();
        m_kalender = new Vector<DTerminkalender>();
        m_gruppen = new Vector<DBenutzerGruppe>();
        m_arten = new Vector<DTerminArt>();
        m_patienten = new Vector<DPatient>();
        m_laender = new Vector<DLand>();
        m_orte = new Vector<DOrt>();
        m_terminArten = new Vector<DTerminArt>();
        m_medikamente = new HashMap<Integer, DMedikament>();
        m_rezepte = new Vector<DRezept>();
        m_verordnungen = new Vector<DMedikamentVerordnung>();
        m_positionen = new Vector<DPosition>();
        m_leistungscodes = new Vector<DLeistungscode>();
        m_behandlungen = new Vector<DBehandlung>();
        m_aerzte = new Vector<DArzt>();
        m_fehlzeiten = new Vector<DFehlzeit>();
        
        // update the cache
	    update();
	    
        // start update thread
	    log.info("starting polling with: " + pollinterval + " msec");
        new Thread(new Runnable() {
            public void run() {
                try {
                    while (true) {
                        Thread.sleep(pollinterval); 
                        update();
                    }
                }
                catch(InterruptedException ex) {/* don't care */}
            }
        }, "brain update").start();
	}
	
    /**
     * reset the cache, forcing an update
     * add the stuff in here, that has to be synchronized
     */
    public synchronized void update() {
        log.debug("... brain update ...");

        m_termine = new Vector<DTermin>();
        m_kalender = new Vector<DTerminkalender>();
        
        // update data
        for(DArzt a : m_aerzte) {
            log.debug("updating queue for: " + a.getBenutzerid());
            a.setWarteschlange(we.getDWarteschlange(a.getBenutzerid()));
            a.setKalender(te.getDTerminKalender(a));
        }
        
        log.trace("current doctor count: " + m_aerzte.size());
    }
    

    /**
     * unregister something from the cache
     * @param o
     */
    public synchronized void unregister(Object o) {
        if (o instanceof DPatient) {
            m_patienten.remove(o);
        } else {
            log.debug("deregister failed for: " + o);
        }
    }
    
	
	/**
	 * return the singleton instance
	 * 
	 * @return
	 */
	public static DomainHandler getInstance() {
	    if (instance == null) {
	        instance = new DomainHandler();
	    }
	    
	    return instance;
	}

	public IBenutzer getActIBenutzer() {
		return actIBenutzer;
	}

	public void setActIBenutzer(IBenutzer actIBenutzer) {
		this.actIBenutzer = actIBenutzer;
	}
    /**
     * @return m_termine
     */
    protected synchronized Vector<DTermin> getTermine() {
        return m_termine;
    }

    /**
     * @return m_benutzer
     */
    protected synchronized Vector<DBenutzer> getBenutzer() {
        return m_benutzer;
    }

    /**
     * @return m_fehlzeiten
     */
    protected synchronized Vector<DFehlzeit> getFehlzeiten() {
        return m_fehlzeiten;
    }

    /**
     * @return m_ordZeiten
     */
    protected synchronized Vector<DOrdinationsZeit> getOrdZeiten() {
        return m_ordZeiten;
    }

    /**
     * @return m_kalender
     */
    protected synchronized Vector<DTerminkalender> getKalender() {
        return m_kalender;
    }

    /**
     * @return m_gruppen
     */
    protected synchronized Vector<DBenutzerGruppe> getGruppen() {
        return m_gruppen;
    }

    /**
     * @return m_arten
     */
    protected synchronized Vector<DTerminArt> getArten() {
        return m_arten;
    }

    /**
     * @return m_patienten
     */
    protected synchronized Vector<DPatient> getPatienten() {
        return m_patienten;
    }

    /**
     * @return m_aerzte
     */
    protected synchronized Vector<DArzt> getAerzte() {
        return m_aerzte;
    }

    /**
     * @return m_laender
     */
    protected synchronized Vector<DLand> getLaender() {
        return m_laender;
    }

    /**
     * @return m_orte
     */
    protected synchronized Vector<DOrt> getOrte() {
        return m_orte;
    }

    /**
     * @return m_terminArten
     */
    protected synchronized Vector<DTerminArt> getTerminArten() {
        return m_terminArten;
    }

    /**
     * @return m_medikamente
     */
    protected synchronized HashMap<Integer, DMedikament> getMedikamente() {
        return m_medikamente;
    }

    /**
     * @return m_behandlungen
     */
    protected synchronized Vector<DBehandlung> getBehandlungen() {
        return m_behandlungen;
    }

    /**
     * @return m_rezepte
     */
    protected synchronized Vector<DRezept> getRezepte() {
        return m_rezepte;
    }

    /**
     * @return m_verordnungen
     */
    protected synchronized Vector<DMedikamentVerordnung> getVerordnungen() {
        return m_verordnungen;
    }

    /**
     * @return m_positionen
     */
    protected synchronized Vector<DPosition> getPositionen() {
        return m_positionen;
    }

    /**
     * @return m_leistungscodes
     */
    protected synchronized Vector<DLeistungscode> getLeistungscodes() {
        return m_leistungscodes;
    }

    /**
     * @param m_termine m_termine to set
     */
    protected synchronized void setTermine(Vector<DTermin> m_termine) {
        this.m_termine = m_termine;
    }

    /**
     * @param m_benutzer m_benutzer to set
     */
    protected synchronized void setBenutzer(Vector<DBenutzer> m_benutzer) {
        this.m_benutzer = m_benutzer;
    }

    /**
     * @param m_fehlzeiten m_fehlzeiten to set
     */
    protected synchronized void setFehlzeiten(Vector<DFehlzeit> m_fehlzeiten) {
        this.m_fehlzeiten = m_fehlzeiten;
    }

    /**
     * @param zeiten m_ordZeiten to set
     */
    protected synchronized void setOrdZeiten(Vector<DOrdinationsZeit> zeiten) {
        m_ordZeiten = zeiten;
    }

    /**
     * @param m_kalender m_kalender to set
     */
    protected synchronized void setKalender(Vector<DTerminkalender> m_kalender) {
        this.m_kalender = m_kalender;
    }

    /**
     * @param m_gruppen m_gruppen to set
     */
    protected synchronized void setGruppen(Vector<DBenutzerGruppe> m_gruppen) {
        this.m_gruppen = m_gruppen;
    }

    /**
     * @param m_arten m_arten to set
     */
    protected synchronized void setArten(Vector<DTerminArt> m_arten) {
        this.m_arten = m_arten;
    }

    /**
     * @param m_patienten m_patienten to set
     */
    protected synchronized void setPatienten(Vector<DPatient> m_patienten) {
        this.m_patienten = m_patienten;
    }

    /**
     * @param m_aerzte m_aerzte to set
     */
    protected synchronized void setAerzte(Vector<DArzt> m_aerzte) {
        this.m_aerzte = m_aerzte;
    }

    /**
     * @param m_laender m_laender to set
     */
    protected synchronized void setLaender(Vector<DLand> m_laender) {
        this.m_laender = m_laender;
    }

    /**
     * @param m_orte m_orte to set
     */
    protected synchronized void setOrte(Vector<DOrt> m_orte) {
        this.m_orte = m_orte;
    }

    /**
     * @param arten m_terminArten to set
     */
    protected synchronized void setTerminArten(Vector<DTerminArt> arten) {
        m_terminArten = arten;
    }

    /**
     * @param m_medikamente m_medikamente to set
     */
    protected synchronized void setMedikamente(
            HashMap<Integer, DMedikament> m_medikamente) {
        this.m_medikamente = m_medikamente;
    }

    /**
     * @param m_behandlungen m_behandlungen to set
     */
    protected synchronized void setBehandlungen(Vector<DBehandlung> m_behandlungen) {
        this.m_behandlungen = m_behandlungen;
    }

    /**
     * @param m_rezepte m_rezepte to set
     */
    protected synchronized void setRezepte(Vector<DRezept> m_rezepte) {
        this.m_rezepte = m_rezepte;
    }

    /**
     * @param m_verordnungen m_verordnungen to set
     */
    protected synchronized void setVerordnungen(
            Vector<DMedikamentVerordnung> m_verordnungen) {
        this.m_verordnungen = m_verordnungen;
    }

    /**
     * @param m_positionen m_positionen to set
     */
    protected synchronized void setPositionen(Vector<DPosition> m_positionen) {
        this.m_positionen = m_positionen;
    }

    /**
     * @param m_leistungscodes m_leistungscodes to set
     */
    protected synchronized void setLeistungscodes(
            Vector<DLeistungscode> m_leistungscodes) {
        this.m_leistungscodes = m_leistungscodes;
    }

}
